/* defines.h */

#ifndef DODO_DEFINES_H
#define DODO_DEFINES_H

//#ifndef NO_NEED_TO_SWAP_ENDIAN
//#define NO_NEED_TO_SWAP_ENDIAN
//#endif

#include <boost/cstdint.hpp>
#include <string>
#include <iostream>
#include <exception>

namespace dodomet
{
namespace mm5
{

/// typedef of the int type used in the MM5 file.
/**
 * it should be 32-bit integer.
 */
typedef boost::int32_t fortran_int;

/// typedef of the real type used in the MM5 file.
/**
 * it should be 32-bit float.
 * if the default float type is not 32-bit long in your system,
 * edit this typedef to make it so.
 */
typedef float fortran_real;

/// typedef of the 2 dummy integers around each fortran record.
typedef boost::uint32_t dummy_t;

/// the value that represents an invalid value in MM5 files
const fortran_int INVALID_VALUE = -999;

/// enum of data_types, aka MM5 program indexes in some functions of the library.
/**
 * see MM5 IO doc.
 */
namespace data_types
{
enum
{
	TERRAIN = 1,
	REGRID = 2,
	LITTLE_R = 3,
	RAWINS_SURFACE = 4,
	INIT_CONDITION = 5,
	LOWER_BOUNDARY = 6,
	LATERAL_BOUNDARY = 7,
	INTERP_PRESSURE = 8,
	OUTPUT_FIRST = 11,
	OUTPUT_LAST = 16,
	OUTPUT_1 = 11,
	OUTPUT_2 = 12,
	OUTPUT_3 = 13,
	OUTPUT_4 = 14,
	OUTPUT_5 = 15,
	OUTPUT_6 = 16
};
} // namespace dodomet::mm5::data_types

/// enum of ordering types.
/**
 * see MM5 IO doc.
 */
namespace ordering_names
{
enum
{
	YXP,
	YXS,
	YXW,
	YX,
	CA,
	XSB,
	YSB,
	XWB,
	YWB,
	P,
	S,
	TOTAL_ORDERING_NUM,
	UNKNOWN = -999
};
} // namespace dodomet::mm5::ordering_names

/// convert ordering index to ordering name string
std::string ordering_to_string(int ordering_index);

/// convert ordering name string to ordering index
int string_to_ordering(const std::string& ordering_name);

/// enum of staggering types.
/**
 * see MM5 IO doc.
 */
namespace staggering_names
{
enum
{
	C,
	D,
	TOTAL_STAGGERING_NUM,
	UNKNOWN = -999
};
} // namespace dodomet::mm5::staggering_names

/// convert staggering index to string.
std::string staggering_to_string(int staggering_index);

/// convert staggering name to index.
int string_to_staggering(const std::string& staggering_name);

/// convert staggering name to index.
int char_to_staggering(char staggering_name);

/// helper function for debugging.
template <class T>
void xxx(const T& stuff)
{
	std::cout << stuff << std::endl;
}

// exceptions
/// exceptions
namespace exceptions
{
/// when file cannot be opened, this will be thrown.
class cannot_open_file : public std::exception
{
public:
	cannot_open_file() {};
	cannot_open_file(const std::string& filename);
	~cannot_open_file() throw() {};
	virtual const char* what() const throw();
private:
	std::string what_;
};

/// when an object is used before initialization, this will be thrown.
class object_uninitialized : public std::exception
{
public:
	object_uninitialized() {};
	object_uninitialized(const std::string& object_what);
	~object_uninitialized() throw() {};
	virtual const char* what() const throw();
private:
	std::string what_;
};

/// nothing throws this yet.
class dodo_mm5_lib_unknown_error : public std::exception
{
};

} // namespace dodomet::mm5::exceptions


} // namespace dodomet::mm5
} // namespace dodomet

#endif //DODO_DEFINES_H

